package hotel.controller.room;

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;

import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.util.Callback;

import java.io.IOException;
import java.net.URL;
import java.util.List;

import org.nutz.dao.QueryResult;
import org.nutz.dao.pager.Pager;

import hotel.common.MsgBox;
import hotel.dao.HotelDao;
import hotel.modal.Room;
import hotel.modal.RoomRent;
import javafx.beans.binding.Bindings;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableView;

import javafx.scene.control.ChoiceBox;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;

public class RoomRentManageController {
	@FXML
	private TableView<RoomRent> tableView;
	@FXML
	private TableColumn<RoomRent, String> preOrderIdCol;
	@FXML
	private TableColumn<RoomRent, String> roomNoCol;
	@FXML
	private TableColumn<RoomRent, String> roomTypeCol;
	@FXML
	private TableColumn<RoomRent, String> nameCol;
	@FXML
	private TableColumn<RoomRent, String> phoneCol;
	@FXML
	private TableColumn<RoomRent, String> startTimeCol;
	@FXML
	private TableColumn<RoomRent, Integer> durationCol;
	@FXML
	private TableColumn<RoomRent, String> statusCol;
	@FXML
	private TableColumn<RoomRent, String> commentCol;
	@FXML
	private Button btnTrailerPage;
	@FXML
	private Button btnHomePage;
	@FXML
	private ChoiceBox<String> condCh;
	@FXML
	private TextField condField;
	@FXML
	private Button btnQuery;
	@FXML
	private Button btnPrevPage;
	@FXML
	private Button btnNextPage;
	@FXML
	private TextField pageField;
	@FXML
	private Label pageCountLabel;
	
	Pager pager = null;
	boolean condSearchMode = false;
	String col = null;
	String cond = null;
	
	@FXML
    public void initialize() {
		setCellFactory();
		
		loadData();
	}
	
	private void loadData() {
		showList(1);
	}
	
	private void showList(int pageNumber) {
		condSearchMode = false;
		ObservableList<RoomRent> data = tableView.getItems();
		QueryResult qrs = HotelDao.getRoomRentList(pageNumber, 500);
		List<RoomRent> list = qrs.getList(RoomRent.class); 	// 获取结果集
		AddRoomRentInfo(list);								// 获取入住订单的客户和房间详细信息
		pager = qrs.getPager(); 							// 获取分页信息
		showPagerInfo();									// 将分页信息显示
		data.setAll(list);
		tableView.refresh();
	}
	
	private List<RoomRent> AddRoomRentInfo(List<RoomRent> list) {
		for(RoomRent t:list) {
			t.setRoom(HotelDao.getRoom(t.getRoomNo()));
			t.setCustomer(HotelDao.getCustomer(t.getCustomerNo()));
		}
		return list;
	}
	
	private void condSearch(int pageNumber) {
		condSearchMode = true;
		col = condCh.getSelectionModel().getSelectedItem();
		cond = condField.getText();
		ObservableList<RoomRent> data = tableView.getItems();
		QueryResult qrs = HotelDao.getRoomRentCondSearch(col, cond, pageNumber, 500);
		List<RoomRent> list = qrs.getList(RoomRent.class); // 获取结果集
		AddRoomRentInfo(list);								// 获取入住订单的客户和房间详细信息
		pager = qrs.getPager(); 							// 获取分页信息
		showPagerInfo();									// 将分页信息显示
		data.setAll(list);
		tableView.refresh();
	}
	
	// Event Listener on Button[#btnQuery].onAction
	@FXML
	public void onBtnQueryAction(ActionEvent event) {
		condSearch(1);
	}

	// Event Listener on Button[#btnTrailerPage].onAction
	@FXML
	public void onBtnTrailerPageAction(ActionEvent event) {
		if (condSearchMode)
			condSearch(pager.getPageCount());
		else
			showList(pager.getPageCount());
	}

	// Event Listener on Button[#btnPrevPage].onAction
	@FXML
	public void onBtnPrevPageAction(ActionEvent event) {
		int page = pager.getPageNumber() - 1;
		if (condSearchMode)
			condSearch(page);
		else
			showList(page);
	}

	// Event Listener on Button[#btnNextPage].onAction
	@FXML
	public void onBtnNextPageAction(ActionEvent event) {
		int page = pager.getPageNumber() + 1;
		if (condSearchMode)
			condSearch(page);
		else
			showList(page);
	}

	// Event Listener on Button[#btnHomePage].onAction
	@FXML
	public void onBtnHomePageAction(ActionEvent event) {
		if (condSearchMode)
			condSearch(1);
		else
			showList(1);
	}
	
	private void itemDetail(RoomRent roomRent) {
		FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/hotel/view/room/RoomRentDetail.fxml"));
		try {
			Parent root = (Parent) fxmlLoader.load();
			RoomRentDetailController controller = fxmlLoader.<RoomRentDetailController>getController();
			controller.setRoomRent(roomRent); // 向子窗口传递数据
			Stage stage = new Stage();
			stage.setScene(new Scene(root));
			stage.setTitle("入住信息详情");
			stage.setResizable(false);
			stage.initModality(Modality.APPLICATION_MODAL);
			stage.show();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private void itemChange(RoomRent roomRent, int mode) {
		URL url = null;
		if(mode == 0)
			url = getClass().getResource("/hotel/view/room/RoomRentChange.fxml");
		else 
			url = getClass().getResource("/hotel/view/room/RentChange.fxml");
		FXMLLoader fxmlLoader = new FXMLLoader(url);
		try {
			Parent root = (Parent) fxmlLoader.load();
			if(mode == 0) {
				RoomRentChangeController controller = fxmlLoader.<RoomRentChangeController>getController();
				controller.setRoomRent(roomRent); // 向子窗口传递数据
			}else {
				RentChangeController controller = fxmlLoader.<RentChangeController>getController();
				controller.setRoomRent(roomRent);
			}
			Stage stage = new Stage();
			stage.setScene(new Scene(root));
			if(mode == 0)
				stage.setTitle("入住信息修改");
			else 
				stage.setTitle("更换房间");
			stage.setResizable(false);
			stage.initModality(Modality.APPLICATION_MODAL);
			stage.showAndWait(); // 显示窗口并等待用户操作
			if (roomRent.isModified()) { // 判断是否被修改
				if (!HotelDao.update(roomRent)) {
					MsgBox.showErrorDialog("错误", "入住信息修改失败！", "没有成功写入数据库！");
				}
				tableView.refresh(); // 刷新表格
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private void showPagerInfo() {
		if(pager == null) return ; 
		pageCountLabel.setText("共 " + pager.getPageCount() + " 页");
		pageField.setText(String.valueOf(pager.getPageNumber()));
		btnPrevPage.setDisable(pager.getPageNumber() <= 1);
		btnNextPage.setDisable(pager.getPageCount() == pager.getPageNumber());
		btnHomePage.setDisable(pager.getPageNumber() == 1);
		btnTrailerPage.setDisable(pager.getPageCount() == pager.getPageNumber());
	}
	
	private void setCellFactory() {
		tableView.setRowFactory(generatedTableViewCallback());
		preOrderIdCol.setCellFactory(generatedStringTableCell());
		roomNoCol.setCellFactory(generatedStringTableCell());
		roomTypeCol.setCellFactory(generatedStringTableCell());
		nameCol.setCellFactory(generatedStringTableCell());
		phoneCol.setCellFactory(generatedStringTableCell());
		startTimeCol.setCellFactory(generatedStringTableCell());
		commentCol.setCellFactory(generatedStringTableCell());
		
		statusCol.setCellFactory(col -> new TableCell<RoomRent, String>() {
			@Override
			protected void updateItem(String item, boolean empty) {
				super.updateItem(item, empty);
				if (empty == true)
					setText(null);
				else if(item == null)
					setText("入住中");
				else if(item.equals("-1"))
					setText("已取消");
				else
					setText("已退房");
				setAlignment(Pos.CENTER);
			}
		});
		
		durationCol.setCellFactory(col -> new TableCell<RoomRent, Integer>() {
			@Override
			protected void updateItem(Integer item, boolean empty) {
				super.updateItem(item, empty);
				if (empty == true)
					setText(null);
				else
					setText(item.toString());
				setAlignment(Pos.CENTER);
			}
		});
		
		// 监听搜索框enter键按下
		condField.setOnKeyPressed(new EventHandler<KeyEvent>() {
			@Override
			public void handle(KeyEvent ke) {
				if (ke.getCode().equals(KeyCode.ENTER)) {
					condSearch(1);
				}
			}
		});
		
		// 监听显示页数框Enter键按下
		pageField.setOnKeyPressed(new EventHandler<KeyEvent>() {
			@Override
			public void handle(KeyEvent ke) {
				if (ke.getCode().equals(KeyCode.ENTER)) {
					int page = Integer.valueOf(pageField.getText());
					if(condSearchMode) condSearch(page);
					else showList(page);
				}
			}
		});
	}
	
	private Callback<TableColumn<RoomRent, String>, TableCell<RoomRent, String>> generatedStringTableCell() {
		return new Callback<TableColumn<RoomRent,String>, TableCell<RoomRent,String>>() {
			@Override
			public TableCell<RoomRent, String> call(TableColumn<RoomRent, String> param) {
				TableCell<RoomRent, String> cell = new TableCell<RoomRent, String>() {
					@Override
					protected void updateItem(String item, boolean empty) {
						super.updateItem(item, empty);
						if (empty == true)
							setText(null);
						else
							setText(item);
						setAlignment(Pos.CENTER);
					}
				};
				return cell;
			}
		};
	}
	
	private Callback<TableView<RoomRent>, TableRow<RoomRent>> generatedTableViewCallback() {
		
		return new Callback<TableView<RoomRent>, TableRow<RoomRent>>() {
			@Override
			public TableRow<RoomRent> call(TableView<RoomRent> param) {
				final TableRow<RoomRent> row = new TableRow<>();

				final ContextMenu rowMenu = new ContextMenu();
				final MenuItem detailItem = new MenuItem("查看详情");
				final MenuItem changeTimeItem = new MenuItem("入住更改");
				final MenuItem changeRoomItem = new MenuItem("更换房间");
				final MenuItem cancelItem = new MenuItem("取消入住");
				rowMenu.getItems().addAll(detailItem, changeTimeItem, changeRoomItem, cancelItem);

				row.itemProperty().addListener(new ChangeListener<RoomRent>() {
					@Override
					public void changed(ObservableValue<? extends RoomRent> observable, RoomRent oldValue,
							RoomRent newValue) {
						if (newValue != null) {
							if(!newValue.isValid() || newValue.getLeaveTime() != null) {
								if(rowMenu.getItems().contains(changeTimeItem))
									rowMenu.getItems().removeAll(changeTimeItem, changeRoomItem, cancelItem);
							}else {
								if(!rowMenu.getItems().contains(changeTimeItem))
									rowMenu.getItems().addAll(changeTimeItem, changeRoomItem, cancelItem);
							}
						}
					}
				});

				row.setOnMouseClicked(event -> { 	// 鼠标双击显示详情
					if (event.getClickCount() == 2 && (!row.isEmpty())) {
						itemDetail(row.getItem());
					}
				});

				detailItem.setOnAction(new EventHandler<ActionEvent>() {
					@Override
					public void handle(ActionEvent event) {
						itemDetail(row.getItem());
					}
				});

				changeTimeItem.setOnAction(new EventHandler<ActionEvent>() {
					@Override
					public void handle(ActionEvent event) {
						itemChange(row.getItem(), 0);
					}
				});
				
				changeRoomItem.setOnAction(new EventHandler<ActionEvent>() {
					@Override
					public void handle(ActionEvent event) {
						itemChange(row.getItem(), 1);
					}
				});

				cancelItem.setOnAction(new EventHandler<ActionEvent>() {
					@Override
					public void handle(ActionEvent event) {
						RoomRent rr = row.getItem();
						rr.setValid(false);
						Room room = HotelDao.getRoom(rr.getRoomNo());
						if (room != null)
							room.setStatus(4);
						if (room != null && HotelDao.update(room) && HotelDao.cancel(rr)) {
							rr.setLeaveTime("-1");
							tableView.refresh();
							MsgBox.showInformationDialog("提醒", null, "成功取消入住！");
							
						} else {
							rr.setValid(true);
							MsgBox.showErrorDialog("错误", null, "更新时发生错误！");
						}
					}
				});

				// only display context menu for non-null items:
				row.contextMenuProperty().bind(Bindings.when(Bindings.isNotNull(row.itemProperty())).then(rowMenu)
						.otherwise((ContextMenu) null));
				return row;
			}
			
		};
	}
}
